<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title></title>
</head>

<body>
	<!--
			js常问：
				如何算设计稿在手机实际显示的尺寸？
					先算出量得的尺寸/设计稿总尺寸的比例，
					再用这个比例，用实际宽度去乘以它，就得出实际要用的尺寸或者边距
				输入地址到生成网页的过程：
					1.浏览器查找ip地址
					2.浏览器给web服务器发送一个HTTP请求
					3.网站服务的永久重定向响应，跟踪重定向地址，有利于优化搜索引擎搜索
					4.服务器“处理”请求，并发回一个HTML响应
					6.浏览器发送获取嵌入在HTML中的对象，比如图片，css，js等资源
				栈：先进后出，堆：队列优先，先进先出
					栈：var b = 0 或者 var c = []
					堆：函数定义，对象定义那些就是堆
				js基本类型：Number Boolean  String  undefined null
				js引用类型：object function
				let，const，var之间的区别：
					const定义的变量不可修改，而且必须初始化					
					var定义的变量可以修改，如果不初始化，会输出undefined，不会报错
					let是块级作用域，函数内部定义了let变量，不会对外部造成影响
				
				灵魂发问：
					[]==![]为什么成立？左边长度0，==左边转换为0，右边是转换为布尔类型为false，0==false，所以成立

                    in和hasOwnProperty的区别：in能访问原型，而另外的不行
					
					
					
					
					
					
					
					
					
				//
				js的原型，原型对象，原型链：
					①所有引用类型都有一个__proto__(隐式原型)属性，属性值是一个普通的对象
					②所有函数都有一个prototype(原型)属性，属性值是一个普通的对象
					③引用类型的__proto__，找到的是它构造函数的prototype,再__proto__，找到根对象原型，再__proto__，就是null
						问：如何分析原型链?
							因为_proto_实质找的是prototype，所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的，它==null。
					根对象是Object，跟原型是object的原型

					比如：new Dms() -- Dms.prototype -- Object.prototype -- null;(Dms.prototype也可以换成class Dms的prototype)
						  [] -- Array.prototype -- Object.prototype -- null;
						  {} -- Object.prototype -- null;
					Object.prototype.isPrototypeOf({}) -> true
				//

				new做了什么

				创建一个新的对象object

				将对象与构建函数通过原型链连接起来

				将构建函数中的this绑定到新建的对象obj上

				根据构建函数返回类型作判断，如果是原始值则被忽略，如果是返回对象，需要当普通函数正常处理
				//
				闭包的概念？用途及运用场景？
					概念：能够读取其他函数内部变量的函数。或简单理解为定义在一个函数内部的函数，内部函数持有外部函数内变量的引用。
					用途：1、读取函数内部的变量
						2、让这些变量的值始终保持在内存中。不会再f1调用后被自动清除。
						3、方便调用上下文的局部变量。利于代码封装。
					运用场景：1.settimeout
							2.回调
							3.封装变量
							4.为节点循环绑定事件	
				为什么要用懒加载？
					1.1 能提升用户的体验，不妨设想下，用户打开像手机淘宝长页面的时候，如果页面上所有的图片都需要加载，由于图片数目较大，等待时间很长，用户难免会心生抱怨,这就严重影响用户体验。
					1.2 减少无效资源的加载，这样能明显减少了服务器的压力和流量，也能够减小浏览器的负担。
					1.3 防止并发加载的资源过多会阻塞js的加载，影响网站的正常使用。
					jq代码：（loaded，data-src为主要）
					 function lazyload(){
			            $('img').each(function (index, value) {
			            
			                if($(this).attr('loaded') == '1')return;
			      
			                if ($(this).offset().top <= $(window).height() + $(document).scrollTop()) {
			                    $(this).attr('src',$(this).attr('data-src')).attr('loaded','1');
			                }
			            })
			         }
			         $(window).scroll(function(){
			            lazyload();
			         }).trigger('scroll');
				事件委托原理以及好处：
					事件委托是利用事件的冒泡原理来实现的，何为事件冒泡呢？就是事件从最深的节点开始，然后逐步向上传播事件
					好处：减少不必要的dom操作，优化网页性能
					实现：
						父级被委托，然后（ev.target || ev.srcElement）.nodeName.toLowerCase()，找节点名的小写处理，等于对应的标签，
						再按正常流程，找到对应属性进行对应的业务操作
					类似事件委托的处理：
					var staffs = document.querySelectorAll('.staff')
					for(var i=0;i<staffs.length;i++){
						(function(index){
							staffs[index].addEventListener('click',function(){
								console.log(index)
							})
						})(i)
					}
				什么是跨域？如何解决？
					浏览器从一个域名的网页去请求另一个域名的资源时，域名、端口、协议任一不同，都是跨域
					解决：1.jsonp跨域 2.nginx方向代理（后台的事）3.PHP端修改header（后台的事）
					jsonp：追加一个带有key=Fn函数这个参数的script脚本（key后台沟通（默认是callback），Fn可以任意），并调用函数，传入res参数，获取参数里面的东西
				阻止页面刷新和后退离开该html，限定后退离开的是html才会又触发：
					window.onbeforeunload = function(e){
						e = e || window.event;
						// 兼容IE8和Firefox 4之前的版本
						if (e) {
							e.returnValue = '关闭提示';
						}
						// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
						return '关闭提示';
					}
				克隆的概念：
					浅度克隆：是复制引用，复制后的引用都是指向同一个对象的实例，彼此之间的操作会互相影响。
					for(var prop in origin){
						if(origin.hasOwnProperty(prop)){
							target[prop] = origin[prop];
						}
					}
					origin旧对象，target新对象
					深度克隆：所有元素或属性均完全复制，与原对象完全脱离，也就是说所有对于新对象的修改都不会反映到原对象中。
					var Nobj = newobj||{}
					for(var i in obj){
						if(typeof obj[i] == 'object'){
							Nobj[i] = obj[i].constructor === 'Array'?[]:{}
							回调(obj[i],Nobj[i])
						}else{
							Nobj[i] = obj[i]
						}
					}
					return Nobj
				call和apply的定义，作用以及区别：
					call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call,apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同.
					call方法:
						语法：fn.call(obj,p1,p2,p3)
						定义：调用一个对象的一个方法，以另一个对象替换当前对象。
						说明：
						call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 obj 指定的新对象。
						如果没有提供 obj 参数，那么 Global 对象被用作 obj。
					apply方法：
						语法：fn.apply(obj,[p1,p2,p3])
						//[p1,p2,p3]为argArray
						定义：应用某一对象的一个方法，用另一个对象替换当前对象。
						说明：
						如果 argArray 不是一个有效的数组或者不是 arguments 对象，那么将导致一个 TypeError。
						如果没有提供 argArray 和 obj 任何一个参数，那么 Global 对象将被用作 obj， 并且无法被传递任何参数
					call, apply作用
						就是借用别人的方法来调用,就像调用自己的一样.
					它们的不同之处：
						apply：
							最多只能有两个参数——新this对象和一个数组
							argArray。如果给该方法传递多个参数，则把参数都写进这个数组里面，当然，即使只有一个参数，也要写进数组里面。如果 argArray
							不是一个有效的数组或者不是 arguments 对象，那么将导致一个 TypeError。如果没有提供 argArray 和 obj任何一个参数，那么 Global 对象将被用作 obj， 并且无法被传递任何参数。
						call：
							则是直接的参数列表，主要用在js对象各方法互相调用的时候，使当前this实例指针保持一致,或在特殊情况下需要改变this指针。如果没有提供 obj 参数，那么 Global 对象被用作 obj。
					更简单地说，apply和call功能一样，只是传入的参数列表形式不同：如 func.call(obj,var1,var2,var3)对应的apply写法为：
					func.apply(obj,[var1,var2,var3])，意思都是第一个参数直接继承给func去使用的时候，func的当前this对象会指向第一个参数，并且会使用后面的参数进行其他业务处理
					bind和call其实用法一样，但不是立即执行，且不兼容ie6-8
				html5离线缓存（window.applicationCache判断是否存在）：
					appcache结尾的文件，给html根元素添加属性manifest然后等于appcache文件的路径即可
					manifest 文件格式					
						顶行写 CACHE MANIFEST					
						CACHE: 换行 指定我们需要缓存的静态资源，如.css、image、js等					
						NETWORK: 换行 指定需要在线访问的资源，可使用通配符					
						FALLBACK: 换行 当被缓存的文件找不到时的备用资源（备用资源路径与当前资源路径之间要有空格）
						【可以指定多个 CACHE NETWORK FALLBACK，无顺序限制】
					特点：可以实现离线浏览，加快加载属度，减少服务器压力
				移动端点击出现300ms延迟的问题：
					解决：使用fastclick这个插件去解决
						if ('addEventListener' in document) {  
						    document.addEventListener('DOMContentLoaded', function() {  
						        FastClick.attach(document.body);  
						    }, false);  
						} 
				防抖与节流：
					函数防抖（debounce）：当持续触发事件时，一定时间段内没有再触发事件，事件处理函数才会执行一次，如果设定的时间到来之前，又一次触发了事件，就重新开始延时。
					节流：每隔一段时间只执行一次函数，
						比如，瀑布流访问数据的时候，到底部时，判断标识是否打开，没打开就打开标识，延迟一秒访问数据，访问数据成功了，然后把数据放完进来，立马关闭标识，再重复操作即可，
				ajax的实现原理及设置请求头和jq的ajax以及设置请求头
					原生四部曲：
						var request;
						if(window.XMLHttpRequest){
						  request=new XMLHttpRequest(); //IE7+,...
						}else{
						  request=new ActiveXObject("Microsoft.XMLHTTP");} //IE6,IE5
						---
						request.open(method,url,async)//async为true的时候为异步
						request.setRequestHeader("Content-type","application/x-www-form-urlencoded");  //post方法，而且必须写在open和send中间
						---
						request.onreadystatechange = function() {
							if(request.readyState == 4 &&request.status == 200) {
								console.log(request.responseText);    
							}
						}
						---
						request.send(参数||null)
					jq的ajax
						$.ajax(
							{
								url:'url',
								type:'post',
								dataType:'json',//指定接收的数据类型
								data:JSON.stringify(org),
								beforeSend: function(xhr) {//请求头设置
									xhr.setRequestHeader("organId:'1333333333'");
								},
								headers:{'Content-Type':'application/json;charset=utf8','organId':'1333333333'},//请求头设置
								success:function(data){console.log("sucess");},//成功返回
								error:function(data){console.log("error");}//失败返回
							}
						);
				function getdate() {
				            var now = new Date(1604926614000),//1604926614*1000ms
				                y = now.getFullYear(),
				                m = now.getMonth() + 1,
				                d = now.getDate();
				            return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d) + " " + now.toTimeString().substr(0, 8);
				        }
				冒泡排序：
					var a=[6,2,4,1,9,5],t;
					for(var i=0;i<a.length;i++){
					  for(var j=0;j<a.length-1;j++){//-1
						 if(a[j]>a[j+1]){//这个成立的时候，保存前面的为临时值，然后互换，前面的等于+1的，然后+1的那个等于临时的
							t=a[j];
							a[j]=a[j+1];
							a[j+1]=t; 
						 }
					   }
					}
					小到大，>,大到小,<
					
				//@链式promise测试======
				function m(type){
					 return new Promise(function(rsv,rjt){
						type?rsv(1):rjt(0)
					})				
				}
				function m2(type){
					 return new Promise(function(rsv,rjt){
						type?rsv(2):rjt(-1)
					})				
				}
				function m3(type){
					 return new Promise(function(rsv,rjt){
						type?rsv(3):rjt(0)
					})				
				}
				m(true).then(function(data){
					console.log(1)
					return m2(true)
				}).then(function(){
					console.log(2)
					return m3(true)
				}).catch(function(data){
					console.log(data,0)
				})//then回调遇到false都会立马跳到最后的catch执行对应返回的catch
				//
				操作属性追加的方法：
					object.assign({},对象)
					Object.defineProperty(对象，属性，{writable: false,value:最终赋给属性的值}）
					----比如Object.defineProperty(window,'opps',{writable: false,value:[333]}
				判断页面是否到达底部
					//变量scrollTop是滚动条滚动时，滚动条上端距离顶部的距离
					var scrollTop = document.documentElement.scrollTop||document.body.scrollTop;
				
					//变量windowHeight是可视区的高度
					var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
				
					//变量scrollHeight是滚动条的总高度（当前可滚动的页面的总高度）
					var scrollHeight = document.documentElement.scrollHeight||document.body.scrollHeight;
				
					//滚动条到底部
					if(scrollTop+windowHeight>=scrollHeight){
						//要进行的操作
					}
		-->
	<!-- 
			如何做大小不一的选择项布局并且可以挤在一起的，
			曲线救国做法：可以做几套模板出来然后随机选取出来，传数据进去使用
			new Date可以追溯到多久之后的时间处理，200000年
		 -->
</body>
<script>
	//call
	function Ner() {
		this.ms = 3
	}
	Ner.prototype.fn = function () {
		return this.ms
	}
	console.log(new Ner().fn.call({ ms: 4 }))

	function mss() {
		console.log(this)
	}
	console.log(mss.call({ ms: 4 }))
</script>

</html>